
#include "slist.h"


namespace	common
{
	slist::slist()
		: head_( nullptr )
		, max_( max )
	{
	}

	slist::~slist()
	{
		destroy();
	}

	bool	slist::create( unsigned short max )
	{
		assert( head_ == nullptr );
		if( head_ != nullptr )
		{
			return false;
		}

		head_ = reinterpret_cast< SLIST_HEADER* >( ::_aligned_malloc( sizeof( SLIST_HEADER ), MEMORY_ALLOCATION_ALIGNMENT ) );
		if( head_ == nullptr )
		{
			return false;
		}

		::InitializeSListHead( head_ );
		max_ = max;
		return true;
	}

	void	slist::destroy()
	{
		if( head_ != nullptr )
		{
			::_aligned_free( head_ );
			head_ = nullptr;
		}

		max_ = max;
	}

	bool	slist::push( SLIST_ENTRY* entry )
	{
		assert( head_ != nullptr );
		assert( entry != nullptr );
		if( head_ != nullptr && entry != nullptr )
		{
			if( count() < max_ )
			{
				::InterlockedPushEntrySList( head_, entry );
				return true;
			}
		}

		return false;
	}

	SLIST_ENTRY*	slist::pop()
	{
		assert( head_ != nullptr );

		SLIST_ENTRY* entry = nullptr;
		if( head_ != nullptr )
		{
			entry = ::InterlockedPopEntrySList( head_ );
		}

		return entry;
	}

	SLIST_ENTRY*	slist::pop_all()
	{
		assert( head_ != nullptr );

		SLIST_ENTRY* entry = nullptr;
		if( head_ != nullptr )
		{
			entry = ::InterlockedFlushSList( head_ );
		}

		return entry;
	}

	unsigned short	slist::count()	const
	{
		assert( head_ != nullptr );

		unsigned short count = 0;
		if( head_ != nullptr )
		{
			count = ::QueryDepthSList( head_ );
		}

		return count;
	}
}
